home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Modules / BackSpaceModules / Source / IconMosaicView / IconMosaicView.m < prev    next >
Text File  |  1993-01-28  |  8KB  |  317 lines

  1. /* IconMosaicView.m -- copyright 1993 by Christopher Lane */
  2.  
  3. #import <c.h>
  4. #import <sys/dir.h>
  5. #import <mach-o/loader.h>
  6. #import <appkit/appkit.h>
  7.  
  8. #import "Thinker.h"
  9. #import "DefaultsTable.h"
  10. #import "IconMosaicView.h"
  11.  
  12. #define MODULE "IconMosaic"
  13. #define DEFAULTSFILE "Defaults.strings"
  14.  
  15. #define IMAGEPATHS getDefault("IconMosaicImagePaths")
  16. #define SEGMENTLIST getDefault("IconMosaicSegmentList")
  17. #define IMAGESUFFIXLIST getDefault("IconMosaicImageSuffixList")
  18. #define APPSUFFIXLIST getDefault("IconMosaicApplicationSuffixList")
  19. #define IGNORESECTIONLIST getDefault("IconMosaicIgnoreSectionList")
  20.  
  21. #define MAXIMUMSIZE getSizeDefault("IconMosaicMaximumSize")
  22. #define MAXIMUMBYTES getIntDefault("IconMosaicMaximumBytes")
  23.  
  24. #define DENSITYDEFAULTNAME "IconMosaicDensity"
  25. #define DENSITY getFloatDefault(DENSITYDEFAULTNAME)
  26.  
  27. #define PATHSEPARATOR "/"
  28. #define PATHSEPARATORCHAR (PATHSEPARATOR)[0]
  29. #define TOKENSEPARATOR ":"
  30. #define TOKENSEPARATORCHAR (TOKENSEPARATOR)[0]
  31. #define EXTENSIONSEPARATOR "."
  32. #define EXTENSIONSEPARATORCHAR (EXTENSIONSEPARATOR)[0]
  33.  
  34. @implementation IconMosaicView
  35.  
  36. static any_t search(id self)
  37. {
  38.     char *path, *paths = NXCopyStringBuffer(IMAGEPATHS);
  39.     
  40.     for(path = strtok(paths, TOKENSEPARATOR); path != NULL; path = strtok(NULL, TOKENSEPARATOR))
  41.         [self loadImagesFromDirectory:path];
  42.         
  43.     NX_FREE(paths);
  44.     
  45.     return self;
  46. }
  47.  
  48. - initFrame:(NXRect *) frameRect
  49. {
  50.     char buffer[MAXPATHLEN];
  51.     
  52.     [super initFrame:frameRect];
  53.  
  54.     [self allocateGState];
  55.  
  56.     images = [[List alloc] init];
  57.     
  58.     inspector = field = nil;
  59.     
  60.     thread = NO_CTHREAD;
  61.     
  62.     lock = mutex_alloc();
  63.     condition = condition_alloc();
  64.     
  65.     (void) sprintf(buffer,"%s/%s", [[NXApp delegate] moduleDirectory:MODULE], DEFAULTSFILE);
  66.     [(defaults = [[DefaultsTable alloc] initFromFile:buffer]) registerDefaults:[NXApp appName]];
  67.  
  68.     maximumSize = MAXIMUMSIZE;
  69.     
  70.     maximumBytes = MAXIMUMBYTES;
  71.     
  72.     srandom(time(NULL));
  73.     
  74.     return self;
  75. }
  76.  
  77. - drawSelf:(const NXRect *) rects :(int) rectCount
  78. {
  79.     if (rects == NULL || rectCount == 0) return self;
  80.     
  81.     PSsetgray(NX_BLACK);
  82.  
  83.     NXRectFill(rects);
  84.  
  85.     return self;
  86. }
  87.  
  88. - didLockFocus
  89. {
  90.     if(thread == NO_CTHREAD) cthread_detach(thread = cthread_fork((cthread_fn_t) search, (any_t) self));
  91.         
  92.     return self;
  93. }
  94.  
  95. - free
  96. {
  97.     mutex_lock(lock); {
  98.         [[images freeObjects] free];
  99.         (void) cthread_abort(thread);
  100.         } mutex_unlock(lock);
  101.         
  102.     return [super free];
  103. }
  104.  
  105. - oneStep
  106. {
  107.     id image;
  108.     NXSize size;
  109.     unsigned int count;
  110.     NXPoint point = { 0, 1 };
  111.     
  112.     condition_signal(condition);
  113.     
  114.     [self scrollRect:&bounds by:&point];
  115.     
  116.     if(((random() % 100) / 100.0) > [density floatValue]) return self;
  117.     
  118.     mutex_lock(lock); {
  119.         count = [images count];
  120.         } mutex_unlock(lock);
  121.     
  122.     if(count < 1) return self;
  123.     
  124.     mutex_lock(lock); {
  125.         [(image = [images objectAt:(random() % count)]) getSize:&size];
  126.         } mutex_unlock(lock);
  127.  
  128.     point.x = random() % (int) (bounds.size.width - size.width);
  129.  
  130.     [image composite:NX_SOVER toPoint:&point];
  131.     
  132.     if(field != nil && [field intValue] < count) [field setIntValue:count];
  133.  
  134.     return self;
  135. }
  136.  
  137. - inspector:sender
  138. {
  139.     char buffer[MAXPATHLEN];
  140.  
  141.     if (inspector == nil) {
  142.         (void) sprintf(buffer,"%s/%s.nib", [sender moduleDirectory:MODULE], MODULE);
  143.         [NXApp loadNibFile:buffer owner:self withNames:NO];
  144.         }
  145.  
  146.     return inspector;
  147. }
  148.  
  149. - inspectorInstalled
  150.     mutex_lock(lock); {
  151.         [field setIntValue:[images count]];
  152.         } mutex_unlock(lock);
  153.  
  154.      return self;
  155. }
  156.  
  157. - (BOOL) useBufferedWindow { return YES; }
  158.  
  159. - (const char *) windowTitle { return MODULE; }
  160.  
  161. - setDefault:sender
  162. {
  163.     [sender setTag:YES];
  164.     
  165.     if([density tag]) (void) writeDefault(DENSITYDEFAULTNAME, [density stringValue]);
  166.  
  167.     return self;
  168. }
  169.  
  170. - setDensity:anObject
  171. {
  172.     [(density = anObject) setFloatValue:DENSITY];
  173.     
  174.     return self;
  175. }
  176.  
  177. - (BOOL) loadFromStream:(NXStream *) stream
  178. {
  179.     NXSize size;
  180.     BOOL result = NO;
  181.     NXImage *image = [[NXImage alloc] init];
  182.  
  183.     if([image loadFromStream:stream]) {
  184.         [image getSize:&size];
  185.         if(size.width <= maximumSize.width && size.height <= maximumSize.height) {
  186.             mutex_lock(lock); {
  187.                 [images addObject:image];
  188.                 condition_wait(condition, lock);
  189.                 } mutex_unlock(lock);
  190.             result = YES;
  191.             }
  192.         else [image free];
  193.         }
  194.     else [image free];
  195.     
  196.     return result;
  197. }
  198.  
  199. - (BOOL) member:(const char *) item ofSet:(const char *) set
  200. {
  201.     BOOL result = NO;
  202.     char *r, *s, *buffer = NXCopyStringBuffer(set);
  203.     int index, length, itemLength = strlen(item);
  204.     
  205.     r = buffer;
  206.     
  207.     while((s = r) != NULL) {
  208.         if((r = index(s, TOKENSEPARATORCHAR)) != NULL) *r++ = '\0';
  209.         
  210.         if((length = strlen(s)) > itemLength) continue;
  211.         else index = itemLength - length;
  212.         
  213.         if(result = (strncmp(s, item + index, length) == 0)) break;
  214.         }
  215.         
  216.     NX_FREE(buffer);
  217.     
  218.     return result;
  219. }
  220.  
  221. - loadImagesFromDirectory:(const char *) directory
  222. {
  223.     struct stat fs;
  224.     NXStream *stream;
  225.     struct direct *dp;
  226.     char buffer[MAXPATHLEN];
  227.     DIR *dirp = opendir(directory);
  228.     
  229.     if(dirp == NULL) return nil;
  230.  
  231.     for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  232.         (void) strcat(strcat(strcpy(buffer, directory), PATHSEPARATOR), dp->d_name);
  233.         if(stat(buffer, &fs) == CERROR) continue;
  234.         else if(fs.st_mode & S_IFDIR && (dp->d_name)[0] != EXTENSIONSEPARATORCHAR) [self loadImagesFromDirectory:buffer];
  235.         else if(fs.st_size <= maximumBytes && [self member:dp->d_name ofSet:IMAGESUFFIXLIST]) {
  236.             if((stream = NXMapFile(buffer, NX_READONLY)) != NULL) {
  237.                 if([self loadFromStream:stream]) {
  238. #ifdef DEBUG
  239.                     (void) fprintf(stderr, "%s\n", buffer);
  240.                     }
  241.                 else {
  242.                     (void) fprintf(stderr, "%s -- failed\n", buffer);
  243. #endif
  244.                     }
  245.                 NXCloseMemory(stream, NX_FREEBUFFER);
  246.                 }
  247.             }
  248.         else if(fs.st_mode & S_IEXEC && fs.st_mode & S_IFREG) [self loadImagesFromSegment:buffer];
  249.         }
  250.  
  251.     (void) closedir(dirp);
  252.     
  253.     return self;
  254. }
  255.  
  256. - loadImagesFromSegment:(const char *) filename
  257. {
  258.     long offset;
  259.     char *buffer;
  260.     unsigned int i;
  261.     NXStream *stream, *memory;
  262.     unsigned long ncmds, nsects;
  263.  
  264.     struct mach_header m_header;
  265.     struct load_command l_command;
  266.     struct segment_command s_command;
  267.     struct section s_section;
  268.  
  269.     if ((stream = NXMapFile(filename, NX_READONLY)) == NULL) return nil;
  270.     if (NXRead(stream, &m_header, sizeof(m_header)) == sizeof(m_header) && m_header.magic == MH_MAGIC) {
  271.     
  272.         for (ncmds = m_header.ncmds; ncmds > 0; ncmds--) {
  273.             offset = NXTell(stream);
  274.             if (NXRead(stream, &l_command, sizeof(l_command)) != sizeof(l_command)) break;
  275.             if (l_command.cmd == LC_SEGMENT) {
  276.                 NXSeek(stream, offset, NX_FROMSTART);
  277.                 if (NXRead(stream, &s_command, sizeof(s_command)) != sizeof(s_command)) break;
  278.                 if([self member:s_command.segname ofSet:SEGMENTLIST]) {
  279.                     for (nsects = 0; nsects < s_command.nsects; nsects++) {
  280.                         if (NXRead(stream, &s_section, sizeof(s_section)) != sizeof(s_section)) continue;
  281.                         else if(s_section.size > maximumBytes || [self member:s_section.sectname ofSet:IGNORESECTIONLIST]) continue;
  282.                     
  283.                         offset = NXTell(stream);
  284.                         NXSeek(stream, s_section.offset, NX_FROMSTART);
  285.  
  286.                         (void) vm_allocate(task_self(), (vm_address_t *) &buffer, (vm_size_t) s_section.size, TRUE);
  287.                         for (i = 0; i < s_section.size; i++) buffer[i] = NXGetc(stream);
  288.                     
  289.                         if((memory = NXOpenMemory(buffer, s_section.size, NX_READONLY)) != NULL) {
  290.                             if([self loadFromStream:memory]) {
  291. #ifdef DEBUG
  292.                                 (void) fprintf(stderr, "%s:%s:%s\n", filename, s_section.segname, s_section.sectname);
  293.                                 }
  294.                             else {
  295.                                 (void) fprintf(stderr, "%s:%s:%s -- failed\n", filename, s_section.segname, s_section.sectname);
  296. #endif
  297.                                 }
  298.                     
  299.                             NXCloseMemory(memory, NX_FREEBUFFER);
  300.                             }
  301.                         NXSeek(stream, offset, NX_FROMSTART);
  302.                         }
  303.                     }
  304.                 else NXSeek(stream, s_command.cmdsize - sizeof(s_command), NX_FROMCURRENT);
  305.                 }
  306.             else NXSeek(stream, l_command.cmdsize - sizeof(l_command), NX_FROMCURRENT);
  307.             }
  308.         }
  309.         
  310.     NXCloseMemory(stream, NX_FREEBUFFER);
  311.     
  312.     return self;
  313. }
  314.  
  315. @end
  316.